﻿using Hydrogen.MarkovChain.SolidMap2DScene;
using Hydrogen.ULib.DataStructure;
using System.Collections.Generic;
using System.Text;

namespace Hydrogen.MarkovChain
{
    /// <summary>
    /// 一个纯色色块，包含一组纯色
    /// </summary>
    public class SolidBlock : SolidBlockBase
    {
        public int Width { get; }
        public int Heigh { get; }
        private TwoDimensionDic<int, int, SolidType> _block;

        private static List<Direction> _directions = new List<Direction>()
        { Direction.L, Direction.R, Direction.U, Direction.D };

        public SolidBlock(string solids) : base(solids)
        {
            var result = Str2Block(solids);
            Width = result.Item1;
            Heigh = result.Item2;
            this._block = result.Item3;
        }


        public override SolidType GetDatumSolid()
        {
            return this._block[0, 0];
        }

        public override bool IsMatch(IMap map, int x, int y, out Direction dir)
        {
            dir = Direction.None;
            if (map == null) return false;

            Utils.RandomArray(_directions);

            foreach (var item in _directions)
            {
                var newBlock = RotateBlock(this._block, Width, Heigh, item);
                bool err = false;// 出现了不匹配的情况
                newBlock.Foreach((nx, ny, t) =>
                {
                    if (map.GetColor(x + nx, y + ny) != t && t != SolidType.Any)
                    {
                        /// 没匹配上，直接跳出循环
                        err = true;
                        return true;
                    }

                    return false;
                });

                if (!err)
                {
                    // 匹配上了，直接返回
                    dir = item;
                    return true;
                }
            }

            return false;
        }

        public override void SetColor(IMap map, int x, int y, Direction dir)
        {
            if (map == null) return;

            var newBlock = RotateBlock(this._block, Width, Heigh, dir);
            newBlock.Foreach((nx, ny, t) =>
            {
                if (t == SolidType.Any) return;
                map.SetColor(x + nx, y + ny, t);
            });
        }









        /// <summary>
        /// 把颜色的字符串，转换成色块
        /// </summary>
        /// <param name="solidsStr"></param>
        /// <returns>Width - Heigh - Block</returns>
        public static (int, int, TwoDimensionDic<int, int, SolidType>) Str2Block(string solidsStr)
        {
            //var solids = Utils.Str2SolidType(solidsStr);
            //TwoDimensionDic<int, int, SolidType> result = new TwoDimensionDic<int, int, SolidType>();
            //for (int i = 0; i < solids.Count; i++)
            //{
            //    result[i, 0] = solids[i];
            //}

            //return (solids.Count, 1, result);
            TwoDimensionDic<int, int, SolidType> result = new TwoDimensionDic<int, int, SolidType>();
            int maxWidth = -1;

            List<string> dim = new List<string>();
            StringBuilder builder = new StringBuilder();
            bool isChecked = false;
            foreach (var item in solidsStr)
            {
                if ('['.Equals(item))
                {
                    isChecked = true;
                    continue;
                }

                if (']'.Equals(item))
                {
                    isChecked = false;
                    dim.Add(builder.ToString());
                    builder.Clear();
                }

                if (isChecked)
                {
                    builder.Append(item);
                    continue;
                }
            }
            if (dim.Count == 0) dim.Add(solidsStr);

            //var dim = solidsStr.Split(']');
            for (int i = 0; i < dim.Count; i++)
            {
                var d1 = Str2Block1D(dim[i].Replace("[","").Replace(" ",""));
                if(d1.Item1>maxWidth)maxWidth = d1.Item1;
                for (int k = 0; k < d1.Item2.Count; k++)
                {
                    result[k, i] = d1.Item2[k];
                }
            }

            return (maxWidth, dim.Count, result);
        }

        private static (int, List<SolidType>) Str2Block1D(string solidsStr)
        {
            var solids = Utils.Str2SolidType(solidsStr);

            return (solids.Count, solids);
        }

        /// <summary>
        /// 旋转色块，使它朝向某一个方向
        /// </summary>
        /// <param name="dir">目标方向</param>
        /// <returns></returns>
        public static TwoDimensionDic<int, int, SolidType> RotateBlock(TwoDimensionDic<int, int, SolidType> block, int width, int heigh, Direction dir)
        {
            if (block == null || width == 0 || heigh == 0) return block;
            if (dir == Direction.R) return block;// 朝右，不旋转
            TwoDimensionDic<int, int, SolidType> result = new TwoDimensionDic<int, int, SolidType>();

            switch (dir)
            {
                case Direction.U:// 朝上，即旋转90°
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < heigh; y++)
                        {
                            result[-y, x] = block[x, y];
                        }
                    }
                    break;
                case Direction.D:// 朝下，即旋转270°
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < heigh; y++)
                        {
                            result[y, -x] = block[x, y];
                        }
                    }
                    break;
                case Direction.L:// 朝左，即旋转180°
                    for (int x = 0; x < width; x++)
                    {
                        for (int y = 0; y < heigh; y++)
                        {
                            result[-x, -y] = block[x, y];
                        }
                    }
                    break;
            }

            return result;
        }


    }
}
